package i5.modelman.chase;

import java.util.Iterator;

import org.apache.log4j.Logger;

import jpl.Query;
import i5.modelman.merge.dependency.Constraint;
import i5.modelman.merge.dependency.ConstraintImpl;
import i5.modelman.merge.dependency.Dependency;

/**
 * A static utility class providing methods for chasing a starting database against a given set of 
 * constraints using a user provided algorithm.
 * 
 * @author lixiang
 *
 */
public class Chaser {
	private static Logger logger = Logger.getLogger(Chaser.class);
	
	private static long chaseCount = 0;
	
	public static void resetChaseCount(){
		chaseCount = 0;
		aggregatedChaseTime = 0;
	}
	public static long getChaseCount(){
		return chaseCount;
	}
	
	private static long aggregatedChaseTime;
	
	public static long getAggregatedChaseTime(){
		return aggregatedChaseTime;
	}
	
	private static Tableau chaseOld(Dependency constraints, Tableau t){
		clearKnowledgeBase();
		
		t.tellTableauToProlog();
		
		tellDependency(constraints);
		
		invokeChase();
		
		Tableau newTab = PrologUtil.createTableauFromProlog();
		
		return newTab;
	}
	
	public static Tableau chase(Tableau t){
		clearFacts();
		
		t.tellTableauToProlog();
		
		invokeChase();
		
		
		Tableau newTab = PrologUtil.createTableauFromProlog();
		
		return newTab;
	}
	
	public static boolean lastChaseFailed(){
		return PrologUtil.booleanQuery("last_chase_failed.");
	}
	
	private static void clearFacts() {
		PrologUtil.clearFacts();
	}
	private static void invokeChase() {
		chaseCount++;
		long start = System.currentTimeMillis();
		PrologUtil.booleanQuery("chase.");
		long end = System.currentTimeMillis();
		reportChaseTime(end-start);
	}

	private static void reportChaseTime(long l) {
		aggregatedChaseTime += l;
	}
	private static void tellDependency(Dependency d) {
		Iterator<Constraint> it = d.getConstraints();
		while(it.hasNext()){
			Constraint c = it.next();
			PrologUtil.tellConstraint(c);
		}
	}

	private static void clearKnowledgeBase() {
		PrologUtil.clearKB();
	}
}
